package com.trace.wells.charactertracker;

import java.util.ArrayList;


import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.BaseExpandableListAdapter;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.Toast;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnChildClickListener;
import android.widget.ToggleButton;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TextView;

public class PrepareSpells extends Activity {

	//The UI interface initializations
	private LayoutInflater inflater;
	private ExpandableListView list;
	private AutoCompleteTextView acTextView;
	private ToggleButton toggleButton;
	private Button prepareButton;
	////////////////////////////////

	//The spellListItems Array list that keeps track of what do draw in the prepare spells screen
	private ArrayList<SpellListItem> spellListItems;

	//Used to determine if the toggle button is selected or not
	private boolean toggleIsChecked;

	//Used to write out the new character data
	private Bundle myChar = new Bundle();

	//The adapter used to draw the expandable list of spells
	private PrepareSpellsExpandableListAdapter spellPrepAdapter;

	//The character imported from the previous activity
	private Character character;

	//A temporary array storing the maximum number of spells able to be added 
	private int[] localMaxSpellsPerLevel;

	//Assigned from the key in myResults. Passed from the previous activity
	private int currentSpellBookView;

	//A temporary spells list that is updated along with the spellListItems ArrayList
	private ArrayList<Spell> spells;

	//Used for returning data to the calling Intent
	private Intent myLocalIntent;

	//The number of spell slots used so far in the Prepare Spells Activity. SHOULD NOT EXCEED MAXSPELLS
	private int[] spellSlotsUsed;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		//Set the view appropriately
		setContentView(R.layout.prepare_spells);

		//Get the data passed from BattleScreen
		Intent data = getIntent();

		//initialize the bundle object with the data received
		Bundle myResults = data.getExtras();

		//Initialize the local character to the character passed
		character = (Character) myResults.getSerializable("character");

		//get the current spellBookView from the data passed
		currentSpellBookView = myResults.getInt("currentView");

		//Assign spellListItems local ArrayList to whatever was in the Character's spellListItems arrayList
		spellListItems = character.characterClass.getSpellListItemArray();

		//If the toggle was checked previously, check it, otherwise, dont... (Keeps track from activity to activity basically...
		toggleIsChecked = character.info.isPrepareSpellsIsChecked();

		//Set the localMaxSpells Array to what is in the character
		localMaxSpellsPerLevel = character.characterClass.getMaximumCastsPerDayArray(currentSpellBookView);

		//Set the spells to what is in the character's spells ArrayList
		spells = character.getSpells(currentSpellBookView);

		//Initialize the spells to be used Array
		spellSlotsUsed = new int[ConstantHelper.SPELL_LEVEL_MAX];

		//Fill up the local 'spells' based on the 'spellListItem' ArrayList
		//initializeSpellListItems();

		//
		//prepareSpellSlotsAvailableArray();


		spellPrepAdapter = new PrepareSpellsExpandableListAdapter();
		spellPrepAdapter.setPrepareSpellArrays();

		list = (ExpandableListView) findViewById(R.id.list);
		toggleButton = (ToggleButton) findViewById(R.id.prepareSpellsToggleButton);
		acTextView = (AutoCompleteTextView) findViewById(R.id.prepareSpellsAutoCompleteTxt);

		initializeAutoCompleteTextView();

		list.setAdapter(spellPrepAdapter);
		list.setGroupIndicator(null);

		for (int i = 0; i <= spellPrepAdapter.getGroupCount(); i++) {
			//			if (character.info.getGroupIsExpandedElement(i) == 1)
			//				list.expandGroup(i);
			if (!list.isGroupExpanded(i))
				list.expandGroup(i);
		}

		initializeFinishedButton();
		spellPrepAdapter.notifyDataSetChanged();

		list.setOnChildClickListener(new OnChildClickListener() {

			@Override
			public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
				Log.d("CHAR", "CLICKED CHILD");
				return true;
			}
		});
	}



	@Override
	protected void onPause() {
		super.onPause();

		//TODO: MOVE TO ON "DONE" CLICK

		//		character.characterClass.setSpellListItemArray(spellListItems);

		//		myChar.putSerializable("character", character);
		//		myLocalIntent.putExtras(myChar);
		//
		//		setResult(Activity.RESULT_OK, myLocalIntent);
		//		finish();
	}

	@Override
	protected void onResume() {
		super.onResume();
	}

	/**
	 * Initializes the button to be pressed when done
	 */
	private void initializeFinishedButton() {
		
		prepareButton = (Button) findViewById(R.id.prepareSpellsPrepareButton);
		
		prepareButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				character.characterClass.setSpellListItemArray(spellListItems);

				myChar.putSerializable("character", character);
				myLocalIntent.putExtras(myChar);

				setResult(Activity.RESULT_OK, myLocalIntent);
				finish();
			}
		});
	}
	
	private void initializeAutoCompleteTextView() {
		int[] spellsSlotsAvailable = character.characterClass.getFreeSpellSlotsSpecial(currentSpellBookView);

		//This function gets all the spells that the user can select from based off the number of free slots available to them at their
		//current level.
		String[] spellStringArrayList = ConstantSpellHelper.concatinateSpellLists(spellsSlotsAvailable, ConstantHelper.classIntToString(currentSpellBookView),
				character.characterClass.getMaxSpellLevelForSpecificClass(currentSpellBookView));

		//The adapter that recieves the layout type from android and the array creatd by the above function.
		//ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, spellStringArray);
		//final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, spellStringArrayList);
		final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, spellStringArrayList);
		//Find the view blah blah blah...

		toggleButton.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
				if (isChecked){
					toggleIsChecked = true;
					character.info.setPrepareSpellsIsChecked(true);
				} else {
					toggleIsChecked = false;
					character.info.setPrepareSpellsIsChecked(false);
				}
			}
		});

		//The amount of letters is needs before it starts auto completing
		acTextView.setThreshold(1);

		//Set that adapter!
		acTextView.setAdapter(adapter);

		acTextView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

				String itemName = adapter.getItem(position);
				boolean spellAlreadyInList;
				
				spellAlreadyInList = false;
				for (SpellListItem sli : spellListItems) {
					if (sli.getName().equalsIgnoreCase(itemName)) {
						spellAlreadyInList = true;
						break;
					}
				}
						
				if (!spellAlreadyInList) {
					FileHelper fh = new FileHelper();
					final Spell spell = fh.getSpellInformationBasedOnName(itemName, PrepareSpells.this, currentSpellBookView);
					
					if (!toggleIsChecked) {

						StringBuffer sb = new StringBuffer();
						for (int i = 1; i < spell.getSpellProperties().size(); i++) {
							sb.append(spell.getConcatinatedHtmlProperty(i));
						}

						final Dialog dialog = new Dialog(PrepareSpells.this);
						dialog.setContentView(R.layout.prepare_spells_spell_information);
						dialog.setTitle(spell.getSpellName());
						dialog.setCancelable(false);

						TextView spellInformaion = (TextView) dialog.findViewById(R.id.prepareSpellsTextView);
						Button viewSpellAdd = (Button) dialog.findViewById(R.id.prepSpellAdd);
						Button viewSpellCancel = (Button) dialog.findViewById(R.id.prepSpellCancel);

						spellInformaion.setText(Html.fromHtml(sb.toString()));

						acTextView.setText("");

						InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
						imm.hideSoftInputFromWindow(spellInformaion.getWindowToken(), 0);

						viewSpellAdd.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View v) {
								spells.add(spell);

								initializeSpellListItems();

								prepareSpellSlotsAvailableArray();

								spellPrepAdapter.setPrepareSpellArrays();
								//initializeAutoCompleteTextView();
								spellPrepAdapter.notifyDataSetChanged();
								dialog.cancel();
							}
						});

						viewSpellCancel.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View v) {
								dialog.cancel();
							}
						});
						dialog.show();

					} else {
						spells.add(spell);

						initializeSpellListItems();

						prepareSpellSlotsAvailableArray();

						spellPrepAdapter.setPrepareSpellArrays();
						//finitializeAutoCompleteTextView();
						spellPrepAdapter.notifyDataSetChanged();
						acTextView.setText("");

						InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
						imm.hideSoftInputFromWindow(list.getWindowToken(), 0);
					}
				} else {
					Toast.makeText(getApplicationContext(), "Spell already exists", Toast.LENGTH_LONG).show();
					acTextView.setText("");
				}
			}
		});
	}

	/**
	 * Will prepare the spellSlotsAvailable array and populate it correctly
	 * depending on the spellListItems ArrayList
	 */
	private void prepareSpellSlotsAvailableArray() {
		spellSlotsUsed = new int[ConstantHelper.SPELL_LEVEL_MAX];
		for (SpellListItem sli : spellListItems) {
			spellSlotsUsed[sli.getLevel()] += sli.getCount();
		}
	}

	private int[] calculateFreeSlotsForEachSpellLevel() {
		int[] returnArray = new int[ConstantHelper.SPELL_LEVEL_MAX];
		for (int i = 0; i < character.characterClass.getMaxSpellLevelForSpecificClass(currentSpellBookView); i++) {
			returnArray[i] = localMaxSpellsPerLevel[i] - spellSlotsUsed[i];
		}
		return returnArray;
	}

	private int calculateTotalSpellsForLevel(int level) {
		int total = 0;
		for (SpellListItem sli : spellListItems) {
			if (sli.getLevel() == level)
				total += sli.getCount();
		}
		return total;
	}

	private void initializeSpellListItems() {
		//spellListItems = character.characterClass.getSpellListItemArray();

		spellListItems.clear();
		//character.characterClass.clearSPellListItem();
		
		for (Spell s : spells) {
			if(!arrayListContains(spellListItems, s.getName())){
				SpellListItem sli = new SpellListItem(s.getName(), 0, s.getSpellLevel(), s.getSpellSchool());
				spellListItems.add(sli);
			}
		}
		

		//		for (Spell s : spells) {
		//
		//			//If the current spell being checked does not have a match in spellListItem...
		//			if (!arrayListContains(spellListItems, s.getName())) {
		//				//Insert the Spell's information into the spellListItem
		//				SpellListItem sli = new SpellListItem(s.getName(), countVal, s.getSpellLevel(), s.getSpellSchool());
		//				//Add it to the compiled list
		//				spellListItems.add(sli);
		//
		//			} else {//if it does exist in the spellListitems, find it and increment the count
		//
		//				//Toast.makeText(getApplicationContext(), "You have already added that spell to the list", Toast.LENGTH_LONG).show();
		//				//				//Loop thorugh all the current sli items
		//				//				for (SpellListItem tempSli : spellListItems) {
		//				//
		//				//					//if one of the items have the same name
		//				//					if (tempSli.getName().equalsIgnoreCase(s.getSpellName())) {
		//				//						//Increment the count of the current one and exit that loop
		//				//						tempSli.incrementCount();
		//				//						break;
		//				//					}
		//				//				}
		//			}
		//		}
		//	}
		
	}

	private boolean arrayListContains(ArrayList<SpellListItem> sli, String spellname) {
		boolean containsSpell = false;
		for (SpellListItem s : sli) {
			if (s.getName().equalsIgnoreCase(spellname))
				containsSpell = true;
		}
		return containsSpell;
	}

	//This class handles the setting and viewing of the group and child elements of the expandable list
	public class PrepareSpellsExpandableListAdapter extends BaseExpandableListAdapter {

		//The array containing the spells remaining 
		int[] groupArray;

		//Get the number of spell levels that character has achieved
		int numSpellLevels = character.characterClass.getMaxSpellLevelForSpecificClass(currentSpellBookView);

		//Used to calculate the total number of group array elements to draw
		int totalLevel;

		private String[] groupData;

		private SpellListItem[][] childrenData;

		//Constructor FTW
		public PrepareSpellsExpandableListAdapter() {
		}

		/**
		 * This wonderful function manages to pull all the character's spell
		 * information and turn it into ledgable, array structured, data that
		 * can be used for the display and interaction of said spells
		 */
		public void setPrepareSpellArrays() {

			inflater = (LayoutInflater) PrepareSpells.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

			numSpellLevels = character.characterClass.getMaxSpellLevelForSpecificClass(currentSpellBookView);
			//groupArray = character.characterClass.getSpellCastsRemainingForSpecificClass(currentSpellBookView);

			//Used to temporarily hold the spells for that level and store them into the array?
			ArrayList<SpellListItem> specificLevelSpells = new ArrayList<SpellListItem>();

			//for every spell level that the character has magic for...
			ArrayList<String> groupArrayListData = new ArrayList<String>();

			childrenData = new SpellListItem[10][1];

			for (int i = 0; i < numSpellLevels; i++) {
				groupArrayListData.add("Level " + i);
				for (SpellListItem sli : spellListItems) {
					if (sli.getLevel() == i)
						specificLevelSpells.add(sli);
				}

				SpellListItem[] tempSLI = new SpellListItem[specificLevelSpells.size()];

				//concatinate the children data into a single array
				for (int k = 0; k < tempSLI.length; k++) {
					SpellListItem item = specificLevelSpells.get(k);
					tempSLI[k] = item;
				}

				childrenData[i] = tempSLI;

				specificLevelSpells.clear();
			}

			//Concatinate the group data into a single array
			String[] groupStringArray = new String[groupArrayListData.size()];
			int count = 0;
			for (String s : groupArrayListData) {
				groupStringArray[count] = s;
				count++;
			}

			//Gets rid of excess slots
			for (int j = numSpellLevels; j < 10; j++) {
				childrenData[j] = null;
			}

			groupData = groupStringArray;
			spellPrepAdapter.notifyDataSetChanged();
		}

		//The temporary holder for the child view. Used for stuff like setting button listeners
		public class ChildViewHolder {
			TextView txtSpellName;
			TextView txtSpellCount;
			Button plusButton;
			Button minusButton;
		}

		//See above comment
		public class GroupViewHolder {
			TextView txtSpellLevel;
			TextView txtTotalSpellsAdded;
		}

		//Gets the child data at the specified position
		public Object getChild(int groupPosition, int childPosition) {
			return childrenData[groupPosition][childPosition];
		}

		//Gets the id of the child
		public long getChildId(int groupPosition, int childPosition) {
			return childPosition;
		}

		//Gets the number of children in the list
		public int getChildrenCount(int groupPosition) {
			return childrenData[groupPosition].length;
		}

		//This part actually is very useful.. Does stuff like Sets data pulled from the adapter, and sets onclickListeners
		//Also an onFling listener here incase there needs to be scrolling back to the main BattleScreen
		public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {

//			tempGroupPos = groupPosition;
//			tempChildPos = childPosition;
			final int groupPos = groupPosition;
			final int childPos = childPosition;
			
			//Sets the groupPosition so it can be used by the clickListener

			//I do not completely understand all of this...
			final ChildViewHolder holder;
			if (convertView == null) {
				//Sets up a new holder to temporaraly hold the listeners that will be assigned to the binded variables
				holder = new ChildViewHolder();
				convertView = inflater.inflate(R.layout.prepare_spells_child_row, null);

				//Find the IDs! Find them!!!!
				holder.txtSpellName = (TextView) convertView.findViewById(R.id.prepareSpellChildNameTxt);
				holder.txtSpellCount = (TextView) convertView.findViewById(R.id.prepareSpellChildCounterTxt);
				holder.plusButton = (Button) convertView.findViewById(R.id.prepareSpellChildPlusButton);
				holder.minusButton = (Button) convertView.findViewById(R.id.prepareSpellChildMinusButton);

				//"Sets the tag associated with this view. A tag can be used
				//to mark a view in its hierarchy and does not have to be unique within the hierarchy."
				convertView.setTag(holder);
			} else {
				holder = (ChildViewHolder) convertView.getTag();
			}
			SpellListItem spellListItem = childrenData[groupPosition][childPosition];
			
			int[] freeSlots = calculateFreeSlotsForEachSpellLevel();

			if (freeSlots[groupPos] < 1)
				holder.plusButton.setEnabled(false);
			else
				holder.plusButton.setEnabled(true);

			if (spellListItem.getCount() == 0)
				holder.minusButton.setEnabled(false);
			else
				holder.minusButton.setEnabled(true);
			
			holder.txtSpellName.setText(spellListItem.getName());
			holder.txtSpellCount.setText(String.valueOf(spellListItem.getCount()));
			holder.minusButton.setText("-");
			holder.plusButton.setText("+");

			holder.plusButton.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					
					SpellListItem spellListItem = (SpellListItem) spellPrepAdapter.getChild(groupPos, childPos);

					spellListItem.incrementCount();

					int replaceIndex = spellListItems.indexOf(spellListItem);

					spellListItems.remove(replaceIndex);
					spellListItems.add(spellListItem);

					spellSlotsUsed[groupPos]++;
					
					holder.txtSpellCount.setText(String.valueOf(spellListItem.getCount()));

					spellPrepAdapter.notifyDataSetChanged();
				}
			});
			
			
			holder.minusButton.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View v) {
					
					SpellListItem spellListItem = (SpellListItem) spellPrepAdapter.getChild(groupPos, childPos);

					spellListItem.decrementCount();

					int replaceIndex = spellListItems.indexOf(spellListItem);

					spellListItems.remove(replaceIndex);
					spellListItems.add(spellListItem);

					spellSlotsUsed[groupPos]--;
					
					holder.txtSpellCount.setText(String.valueOf(spellListItem.getCount()));

					spellPrepAdapter.notifyDataSetChanged();
				}
			});

			holder.txtSpellName.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					Log.d("CHAR", "CLICKED SPELL FOR INFO");
					Spell tempSpell = character.getSpellBasedOnName(holder.txtSpellName.getText().toString(), currentSpellBookView);
					if (tempSpell != null) {
						StringBuffer sb = new StringBuffer();
						for (int i = 1; i < tempSpell.getSpellProperties().size(); i++) {
							sb.append(tempSpell.getConcatinatedHtmlProperty(i));
						}
						final Dialog dialog = new Dialog(PrepareSpells.this);
						dialog.setContentView(R.layout.prepare_spell_about_spell);
						dialog.setTitle(tempSpell.getSpellName());
						dialog.setCancelable(true);

						TextView spellInformaion = (TextView) dialog.findViewById(R.id.prepareSpellsTextView);
						Button viewSpellCancel = (Button) dialog.findViewById(R.id.prepSpellCancel);

						spellInformaion.setText(Html.fromHtml(sb.toString()));

						viewSpellCancel.setOnClickListener(new OnClickListener() {

							@Override
							public void onClick(View v) {
								dialog.cancel();
							}
						});

						dialog.show();
					}
				}
			});

			return convertView;
		}

		public Object getGroup(int groupPosition) {
			return groupData[groupPosition];
		}

		public int getGroupCount() {
			return groupData.length;
		}

		public long getGroupId(int groupPosition) {
			return groupPosition;
		}

		public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {

			GroupViewHolder holder;
			if (convertView == null) {
				holder = new GroupViewHolder();
				convertView = inflater.inflate(R.layout.spell_group_row, null);

				holder.txtSpellLevel = (TextView) convertView.findViewById(R.id.battlemagicSpellRowLevelTxt);
				holder.txtTotalSpellsAdded = (TextView) convertView.findViewById(R.id.battlemagicSpellRowRemainingTxt);

				convertView.setTag(holder);
			} else {
				holder = (GroupViewHolder) convertView.getTag();
			}
			String groupInfo = groupData[groupPosition];

			holder.txtSpellLevel.setText(groupInfo);

			holder.txtTotalSpellsAdded.setText(String.valueOf(calculateTotalSpellsForLevel(groupPosition)) + " of " + localMaxSpellsPerLevel[groupPosition]);

			return convertView;
		}

		public boolean hasStableIds() {
			return false;
		}

		public boolean isChildSelectable(int groupPosition, int childPosition) {
			return false;
		}

	}
}

class SpellListItem {
	String name;
	int count;
	int level;
	String school;

	public SpellListItem(String name, int count, int level, String school) {
		super();
		this.name = name;
		this.count = count;
		this.level = level;
		this.school = school;
	}

	public SpellListItem() {
		super();
	}

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name
	 *            the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the count
	 */
	public int getCount() {
		return count;
	}

	/**
	 * @param count
	 *            the count to set
	 */
	public void setCount(int count) {
		this.count = count;
	}

	public void incrementCount() {
		this.count++;
	}

	public void decrementCount() {
		this.count--;
	}

	/**
	 * @return the level
	 */
	public int getLevel() {
		return level;
	}

	/**
	 * @param level
	 *            the level to set
	 */
	public void setLevel(int level) {
		this.level = level;
	}

	/**
	 * @return the school
	 */
	public String getSchool() {
		return school;
	}

	/**
	 * @param school
	 *            the school to set
	 */
	public void setSchool(String school) {
		this.school = school;
	}
}
